﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
namespace Odyssey.Consul
{
    using Http;

    internal static class OdysseyHttpRequesterExtension
    {
        private static HttpMethod ToNetHttpMethod(this EnumConsulHttpMethod enumConsulHttpMethod)
        {
            var httpMethod = HttpMethod.Post;
            switch (enumConsulHttpMethod)
            {
                case EnumConsulHttpMethod.Get:
                    httpMethod = HttpMethod.Get;
                    break;
                case EnumConsulHttpMethod.Post:
                    httpMethod = HttpMethod.Post;
                    break;
                case EnumConsulHttpMethod.Put:
                    httpMethod = HttpMethod.Put;
                    break;
                case EnumConsulHttpMethod.Delete:
                    httpMethod = HttpMethod.Delete;
                    break;
            }
            return httpMethod;
        }

        public static async Task<TResult> ConsulSendAsync<TResult>(this IHttpRequester httpRequester, string uri, EnumConsulHttpMethod httpMethod, IDictionary<string, string> heads = null)
        {
            return await httpRequester.ConsulSendAsync<string, TResult>(uri, string.Empty, httpMethod, heads);
        }

        public static async Task<TResult> ConsulSendAsync<TArgument, TResult>(this IHttpRequester httpRequester, string uri, TArgument argument, EnumConsulHttpMethod httpMethod, IDictionary<string, string> heads = null)
        {
            switch (httpMethod)
            {
                case EnumConsulHttpMethod.Get:
                    return await httpRequester.GetAsync<TResult>(uri, requestHeaders: heads);
                case EnumConsulHttpMethod.Post:
                    return await httpRequester.PostAsync<TArgument, TResult>(uri, argument, requestHeaders: heads);
                case EnumConsulHttpMethod.Put:
                    return await httpRequester.PutAsync<TArgument, TResult>(uri, argument, requestHeaders: heads);
                case EnumConsulHttpMethod.Delete:
                    return await httpRequester.DeleteAsync<TArgument, TResult>(uri, argument, requestHeaders: heads);
                default:
                    throw new ArgumentException(nameof(httpMethod));
            }
        }

        public static async Task<string> ConsulSendAsync(this IHttpRequester httpRequester, string uri, EnumConsulHttpMethod httpMethod, IDictionary<string, string> heads = null)
        {
            switch (httpMethod)
            {
                case EnumConsulHttpMethod.Get:
                    return await httpRequester.GetAsync(uri, requestHeaders: heads);
                case EnumConsulHttpMethod.Post:
                    return await httpRequester.PostStringAsync(uri, string.Empty, requestHeaders: heads);
                case EnumConsulHttpMethod.Put:
                    return await httpRequester.PutStringAsync(uri, string.Empty, requestHeaders: heads);
                case EnumConsulHttpMethod.Delete:
                    return await httpRequester.DeleteStringAsync(uri, string.Empty, requestHeaders: heads);
                default:
                    throw new ArgumentException(nameof(httpMethod));
            }
        }

        public static async Task<HttpResponseMessage> ConsulSendAsync(this IHttpRequester httpRequester, string uri, object data = null, EnumConsulHttpMethod enumConsulHttpMethod = EnumConsulHttpMethod.Post, IDictionary<string, string> heads = null)
        {
            var httpMethod = enumConsulHttpMethod.ToNetHttpMethod();
            return await httpRequester.SendAsync(new Uri(uri), data, httpMethod, requestHeaders: heads);
        }

        public static async Task<HttpResponseMessage> ConsulSendAsync(this IHttpRequester httpRequester, string uri, byte[] data = null, EnumConsulHttpMethod enumConsulHttpMethod = EnumConsulHttpMethod.Post, IDictionary<string, string> heads = null)
        {
            var httpMethod = enumConsulHttpMethod.ToNetHttpMethod();
            return await httpRequester.SendAsync(new Uri(uri), data, httpMethod, requestHeaders: heads);
        }
    }
}
